package com.liuweiheng.base.aop;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.liuweiheng.base.entity.LogResult;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局日志记录
 * TODO 日志分多行打印时，在高压环境下，会出现打印乱行的情况，需封装成对象，进行json格式输出即可
 * @author lwh
 * @since 2021/6/2
 */
@Aspect
@Component
public class GlobalLogAspect {
    Logger log = LoggerFactory.getLogger(GlobalLogAspect.class);

    public static final String REQUEST_ATTR_LOGKEY = "LOG_RESULT";

    @Pointcut("execution(* com.liuweiheng.cloud.controller.*Controller.*(..))")
    public void doLog() {}

    @Before("doLog()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        LogResult result = LogResult.builder()
                .requestMethod(request.getMethod())
                .classMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName())
                .startTime(DateUtil.now())
                .build();

        request.setAttribute(REQUEST_ATTR_LOGKEY, result);

    }

    @After("doLog()")
    public void doAfter(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        LogResult result = (LogResult) attributes.getRequest().getAttribute(REQUEST_ATTR_LOGKEY);
        result.setEndTime(DateUtil.now());
        log.info("Request INFO：{}", JSONUtil.parse(result));
    }

}
